package tcpserver.handler.in;

import frame.util.ByteUtil;
import frame.util.Ref;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import tcpserver.RFIDSessionManager;

import java.util.List;

// [FrameHead: 1] + [ControlWord: 2] + [DataLength: 2] + [Data: DataLength] + [CRC: 2]

public class FrameSeparator extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

        while(discardUntilTouchFrameHead(in)) tryDisjoint(in).ifPresent(out::add);
    }

    private boolean discardUntilTouchFrameHead(ByteBuf in) {

        while(in.readableBytes() > 0 && Byte.toUnsignedInt(in.getByte(0)) != 0xaa) in.readByte();

        return in.readableBytes() > 0;
    }

    private Ref<byte[]> tryDisjoint(ByteBuf in) {

        if(in.readableBytes() <= 5) return Ref.empty();

        int dataLength = Short.toUnsignedInt(ByteUtil.bytePairToShort(in.getByte(3), in.getByte(4)));

        if(in.readableBytes() < 5 + dataLength + 2) return Ref.empty();

        return Ref.of(moveAndRelease(in.readBytes(5 + dataLength + 2)));
    }

    private byte[] moveAndRelease(ByteBuf buffer) {

        byte[] tmp = new byte[buffer.readableBytes()];

        buffer.readBytes(tmp).release();

        return tmp;
    }
}
